package demo.dcs.util;

/**
 * created by dongbo on 2019/10/29
 * <p>
 * 判断类、方法、属性是否存在，主要用于判断mainstay3的线程池和连接池，兼容版本问题
 */
public class ClassPresentUtil {
    //由于以下类在3.0.19 之后才有，所以收集方需要check 该类以及方法是否存在，都存在说明才能收集
    private static final String mainstay3StandardThreadExecutorStat = "com.ximalaya.mainstay.common.concurrent.StandardThreadExecutorStat";
    private static final String mainstay3StandardThreadExecutor = "com.ximalaya.mainstay.common.concurrent.StandardThreadExecutor";
    private static final String maisntay3StandardThreadExecutorMethod = "stat";

    private static final String mainstay3NettyClient = "com.ximalaya.mainstay.transport.netty.NettyClient";
    private static final String mainstay3NettyClientStat = "com.ximalaya.mainstay.transport.netty.model.NettyClientStat";
    private static final String mainstay3NettyClientManager = "com.ximalaya.mainstay.transport.netty.NettyClientManager";
    private static final String maisntay3NettyClientStatMethod = "stat";
    private static final String mainstay3NettyClientManagerField = "ALL_NETTY_CLIENT";

    private static final String mainstay3NettyServer = "com.ximalaya.mainstay.transport.netty.NettyServer";
    private static final String mainstay3NettyServerStat = "com.ximalaya.mainstay.transport.netty.model.NettyServerStat";
    private static final String mainstay3NettyServerStatMethod = "stat";
    private static final String maisntay3NettyServerManager = "com.ximalaya.mainstay.transport.netty.NettyServerManager";
    private static final String maisntay3NettyServerManagerField = "ALL_NETTY_SERVER";

    public static boolean isMainstay3StandardThreadExecutorMonitor() {
        if (isClassPresent(mainstay3StandardThreadExecutorStat)
                && isClassPresent(mainstay3StandardThreadExecutor)
                && isMethodPresent(mainstay3StandardThreadExecutor, maisntay3StandardThreadExecutorMethod)) {

            return true;
        }

        return false;
    }

    public static boolean isMainstay3NettyClientMonitor() {
        if (isClassPresent(mainstay3NettyClient)
                && isClassPresent(mainstay3NettyClientStat)
                && isClassPresent(mainstay3NettyClientManager)
                && isMethodPresent(mainstay3NettyClient, maisntay3NettyClientStatMethod)
                && isFieldPresent(mainstay3NettyClientManager, mainstay3NettyClientManagerField)) {

            return true;
        }

        return false;
    }

    public static boolean isMainstay3NettyServerMonitor() {
        if (isClassPresent(mainstay3NettyServer)
                && isClassPresent(mainstay3NettyServerStat)
                && isClassPresent(maisntay3NettyServerManager)
                && isMethodPresent(mainstay3NettyServer, mainstay3NettyServerStatMethod)
                && isFieldPresent(maisntay3NettyServerManager, maisntay3NettyServerManagerField)) {

            return true;
        }

        return false;
    }

    /**
     * 判断当前类是否存在
     *
     * @param classPath
     * @return
     */
    public static boolean isClassPresent(String classPath) {
        boolean isPresent;
        try {
            isPresent =
                    null != Class.forName(classPath);
        } catch (Throwable t) {
            isPresent = false;
        }

        return isPresent;
    }

    public static boolean isMethodPresent(String className, String methodName) {
        boolean isMethodPresent = true;
        Class cls = null;
        try {
            cls = Class.forName(className);
        } catch (Throwable t) {
            return false;
        }

        try {
            if (cls == null) {
                isMethodPresent = false;
            } else {
                cls.getDeclaredMethod(methodName);
            }
        } catch (NoSuchMethodException e) {
            isMethodPresent = false;
        }

        return isMethodPresent;
    }

    public static boolean isFieldPresent(String className, String fieldName) {
        boolean isPresent = true;
        Class cls = null;
        try {
            cls = Class.forName(className);
        } catch (Throwable t) {
            return false;
        }

        try {
            if (cls == null) {
                isPresent = false;
            } else {
                cls.getDeclaredField(fieldName);
            }
        } catch (NoSuchFieldException e) {
            isPresent = false;
        }

        return isPresent;
    }

}
